home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / mtask.exe / MTASK.C < prev    next >
C/C++ Source or Header  |  1993-05-09  |  6KB  |  337 lines

  1. /* MTASK V1.0
  2.  
  3.   A minimal multitasking library for DOS.  Copyright 1993 I H Ting.
  4.  
  5.   Disclaimer:
  6.   Use the code at your own peril. I don't promise it actually does anything.
  7.   Even if the world ends when you use it, don't hold me responsible. 
  8.  
  9.   Comments and suggestions, however, are welcomed. I can be reached at:
  10.  
  11.   Compuserve ID: 100023,3363
  12.   Internet: cm1826@ccub.wlv.ac.uk
  13.  
  14. */
  15.  
  16. #include "stdio.h"
  17. #include "dos.h"
  18. #include "stdlib.h"
  19. #include "conio.h"
  20. #include "mtask.h"
  21.  
  22. enum TaskStatus {INVALID, CURRENT, READY, WAITING};
  23.  
  24. typedef struct {
  25.   unsigned bp;
  26.   unsigned di;
  27.   unsigned si;
  28.   unsigned ds;
  29.   unsigned es;
  30.   unsigned dx;
  31.   unsigned cx;
  32.   unsigned bx;
  33.   unsigned ax;
  34.   unsigned ip;
  35.   unsigned cs;
  36.   unsigned flags;
  37. } RegsOnStack;
  38.  
  39.  
  40. typedef struct {
  41.   unsigned sp;
  42.   unsigned ss;
  43.   enum TaskStatus status; 
  44.   unsigned *semaphore;      
  45.   void *pOwnStack;    
  46. } TaskInfo;
  47.  
  48. TaskInfo taskList[MAX_TASKS];
  49.  
  50.  
  51. void interrupt TheScheduler(void);
  52. void interrupt ChangeTask(void);
  53. void interrupt (*PrevInterrupt)(void);
  54. void WakeUpTasks(unsigned *semaphore);
  55. void EndMultiTasking(void);
  56. void TidyUp(void);
  57. int IsDeadLock(void);
  58.  
  59.  
  60.  
  61.  
  62. static unsigned originalSS, originalSP;
  63. static unsigned IOsemaphore=0;  
  64.  
  65. static int currentTaskID = 0;      
  66. static char bMultiTasking = 1;     
  67.  
  68.  
  69. static void interrupt TheScheduler(void)
  70. {
  71.   (*PrevInterrupt)();  
  72.   taskList[currentTaskID].ss = _SS;  
  73.   taskList[currentTaskID].sp = _SP;
  74.  
  75.   if(taskList[currentTaskID].status==CURRENT) 
  76.      taskList[currentTaskID].status = READY;
  77.  
  78.   if(IsDeadLock()) bMultiTasking = 0;
  79.  
  80.   if(!bMultiTasking) { /* stop bMultiTasking */
  81.     disable();
  82.     _SS = originalSS;
  83.     _SP = originalSP;
  84.     setvect(8, PrevInterrupt);
  85.     TidyUp();
  86.     enable();
  87.     return;
  88.   }
  89.  
  90.   do{
  91.     currentTaskID++;
  92.     if(currentTaskID==MAX_TASKS) currentTaskID = 0;
  93.   }while(taskList[currentTaskID].status!=READY); 
  94.  
  95.   _SS = taskList[currentTaskID].ss;  
  96.   _SP = taskList[currentTaskID].sp;
  97.   taskList[currentTaskID].status = CURRENT; 
  98.  
  99. }
  100.  
  101. static void interrupt ChangeTask(void)
  102. {
  103.  
  104.   disable();
  105.   taskList[currentTaskID].ss = _SS;
  106.   taskList[currentTaskID].sp = _SP;
  107.   if(taskList[currentTaskID].status==CURRENT)
  108.     taskList[currentTaskID].status = READY;
  109.  
  110.   if(IsDeadLock()) bMultiTasking = 0;
  111.  
  112.   if(!bMultiTasking) { 
  113.     disable();
  114.     _SS = originalSS;
  115.     _SP = originalSP;
  116.     setvect(8, PrevInterrupt);
  117.     TidyUp();
  118.     enable();
  119.     return;
  120.   }
  121.  
  122.     /* find new pTaskFunc */
  123.   do{
  124.     currentTaskID++;
  125.     if(currentTaskID==MAX_TASKS) currentTaskID = 0;
  126.   }while(taskList[currentTaskID].status!=READY);
  127.   
  128.   _SS = taskList[currentTaskID].ss;
  129.   _SP = taskList[currentTaskID].sp;
  130.   taskList[currentTaskID].status = CURRENT;
  131.   enable();
  132. }
  133.  
  134.  
  135. static int IsDeadLock(void)
  136. {
  137.   register int i;
  138.  
  139.   for(i=0; i<MAX_TASKS; i++) 
  140.     if(taskList[i].status==READY) return 0;
  141.   return 1;
  142. }
  143.  
  144.  
  145. static void TidyUp(void)
  146. {
  147.   int i;
  148.  
  149.   for(i=0; i<MAX_TASKS; i++) {
  150.     if(taskList[i].pOwnStack) {
  151.       free(taskList[i].pOwnStack);
  152.       taskList[i].pOwnStack = NULL;
  153.     }
  154.   }
  155. }
  156.  
  157.  
  158. int AddNewTask(PTaskFunc pTaskFunc)
  159. {
  160.   RegsOnStack *pRegs;
  161.   unsigned taskID, i;
  162.   void *pNewStack;
  163.  
  164.  
  165.   disable();  
  166.   taskID = MAX_TASKS;
  167.   for(i=0; i<MAX_TASKS; i++)
  168.     if (taskList[i].status == INVALID){
  169.       taskID = i;
  170.       break;
  171.     }
  172.   if (taskID == MAX_TASKS){  /* Failed */
  173.     enable();
  174.     return taskID;
  175.   }
  176.  
  177.   pNewStack = malloc(TASK_STACK_SIZE + sizeof(RegsOnStack));
  178.   if (pNewStack==NULL) return MAX_TASKS;
  179.   taskList[taskID].pOwnStack = pNewStack;
  180.   pRegs = (RegsOnStack *) taskList[taskID].pOwnStack + 
  181.         TASK_STACK_SIZE - sizeof(RegsOnStack);
  182.  
  183.   taskList[taskID].sp = FP_OFF((RegsOnStack far *) pRegs);
  184.   taskList[taskID].ss = FP_SEG((RegsOnStack far *) pRegs);
  185.  
  186.   pRegs->cs = FP_SEG(pTaskFunc);
  187.   pRegs->ip = FP_OFF(pTaskFunc);
  188.   pRegs->ds = _DS;
  189.   pRegs->es = _DS;
  190.   pRegs->flags = 0x200;
  191.  
  192.   taskList[taskID].status = READY;
  193.   enable();
  194.   return taskID;
  195. }
  196.  
  197.  
  198. void interrupt StartMultiTasking(void)
  199. {
  200.   disable();
  201.  
  202.   PrevInterrupt = getvect(8);
  203.   setvect(8, TheScheduler);
  204.  
  205.   originalSS = _SS;
  206.   originalSP = _SP;
  207.  
  208.   _SS = taskList[currentTaskID].ss;
  209.   _SP = taskList[currentTaskID].sp;
  210.   enable();
  211. }
  212.  
  213.  
  214. void RemoveTask(unsigned taskID)
  215. {
  216.   disable();
  217.   if(taskID <MAX_TASKS){
  218.     taskList[taskID].status = INVALID;
  219.     if(taskList[taskID].pOwnStack)
  220.       free(taskList[taskID].pOwnStack);
  221.     taskList[taskID].pOwnStack = NULL;
  222.   }
  223.   enable();
  224.   ChangeTask(); 
  225. }
  226.  
  227.  
  228. void InitMultiTasking(void)
  229. {
  230.   int i;
  231.  
  232.   for(i=0; i<MAX_TASKS; i++) {
  233.     taskList[i].status = INVALID;
  234.     taskList[i].semaphore = NULL;
  235.     taskList[i].pOwnStack = NULL;
  236.   }
  237. }
  238.  
  239.  
  240. void EndMultiTasking(void)
  241. {
  242.   bMultiTasking = 0;
  243.   ChangeTask();
  244. }
  245.  
  246.  
  247.  
  248.  
  249. void MTWait(unsigned *semaphore)
  250. {
  251.   disable();
  252.   while(*semaphore) {
  253.     taskList[currentTaskID].status = WAITING;
  254.     taskList[currentTaskID].semaphore = semaphore;
  255.     ChangeTask();
  256.     disable();
  257.   }
  258.   *semaphore = 1;
  259.   enable();
  260. }
  261.  
  262. void MTSignal(unsigned *semaphore)
  263. {
  264.   disable();
  265.   taskList[currentTaskID].semaphore = NULL;
  266.   *semaphore = 0;
  267.   WakeUpTasks(semaphore);
  268.   ChangeTask();
  269.   enable();
  270. }
  271.  
  272. static void WakeUpTasks(unsigned *semaphore)
  273. {
  274.   int i;
  275.  
  276.   for(i=0; i<MAX_TASKS; i++)
  277.     if(taskList[i].semaphore == semaphore) {
  278.       taskList[i].semaphore = NULL;
  279.       if(taskList[i].status == WAITING) 
  280.         taskList[i].status = READY;
  281.       return;
  282.     }
  283. }
  284.  
  285.  
  286.  
  287.  
  288. void MTPuts(char *s)
  289. {
  290.   MTWait(&IOsemaphore);
  291.   puts(s);
  292.   MTSignal(&IOsemaphore);
  293. }
  294.  
  295. void MTXYPuts(int x,int y,char *s)
  296. {
  297.   MTWait(&IOsemaphore);
  298.   gotoxy(x,y);
  299.   cputs(s);
  300.   MTSignal(&IOsemaphore);
  301. }
  302.  
  303.  
  304. char MTGetch(void)
  305. {
  306.   char ch;
  307.  
  308.   MTWait(&IOsemaphore);
  309.   if (kbhit()) ch = getch();
  310.   else ch = 0;
  311.   MTSignal(&IOsemaphore);
  312.   return ch;
  313. }
  314.  
  315. void MTPutch(char c)
  316. {
  317.   MTWait(&IOsemaphore);
  318.   putch(c);
  319.   MTSignal(&IOsemaphore);
  320. }
  321.  
  322.  
  323. void MTXYPutch(int x, int y, char c)
  324. {
  325.   MTWait(&IOsemaphore);
  326.   gotoxy(x,y);
  327.   putch(c);
  328.   MTSignal(&IOsemaphore);
  329. }
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.